package com.blueocean_health.care.management.service;

import static org.hamcrest.CoreMatchers.nullValue;
import static org.mockito.Matchers.booleanThat;
import static org.mockito.Matchers.intThat;
import static org.mockito.Mockito.stubVoid;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.xmlbeans.impl.xb.xsdschema.TotalDigitsDocument.TotalDigits;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.blueocean_health.care.management.common.base.em.TimeType;
import com.blueocean_health.care.management.common.base.string.StringUtils;
import com.blueocean_health.care.management.common.base.time.TimeUtils;
import com.blueocean_health.care.management.common.consts.SysConstant;
import com.blueocean_health.care.management.domain.base.Hospital;
import com.blueocean_health.care.management.domain.base.SysResult;
import com.blueocean_health.care.management.domain.dto.DepartmentCountReport;
import com.blueocean_health.care.management.domain.dto.DepartmentDailyReport;
import com.blueocean_health.care.management.domain.dto.OrderNurseDailyReport;
import com.blueocean_health.care.management.domain.dto.OrderNurseFullDto;
import com.blueocean_health.care.management.domain.dto.PullDownDto;
import com.blueocean_health.care.management.domain.ordervo.DepartmentReportVo;
import com.blueocean_health.care.management.domain.ordervo.OrderNurseDailyVo;
import com.blueocean_health.care.management.domain.worktablevo.NurseWokerStatistics;
import com.blueocean_health.care.management.domain.worktablevo.NurseWorker;
import com.blueocean_health.care.management.em.OrderTypeEnum;
import com.blueocean_health.care.management.em.ServiceTypeEnum;
import com.blueocean_health.care.management.mapper.DepartmentMapper;
import com.blueocean_health.care.management.mapper.IParamDao;
import com.blueocean_health.care.management.mapper.NurseGroupMapper;
import com.blueocean_health.care.management.mapper.ReportMapper;
import com.google.gson.JsonObject;
import com.google.gson.annotations.JsonAdapter;
import com.itextpdf.text.pdf.PdfStructTreeController.returnType;


/**
 * @author 作者: zwg.BlueOcean
 * @date 创建时间：2017年8月30日 下午3:24:47
 * @version 版本号： 1.0*
 * @parameter *
 * @since *
 * @return *
 * @description *
 */
@Service
public class ReportServiceImpl implements ReportService {
	@Autowired
	private HospitalService hospitalService;
	@Autowired
	private ReportMapper dao;
	@Autowired
	private RecordTimeMatcherService matcher;
	@Autowired
	private DepartmentMapper deparmnetDao;
	@Autowired
	private NurseGroupMapper nurseGroupDao;
	
	
	//根据查询条件，查询出符合条件护工日报数据
	@Override
	public List<OrderNurseDailyReport> findNurseDailyListData(OrderNurseDailyVo qvo, String hospitalId) {
		String dateStart = qvo.getDate() + " 00:00:00";
		String dateEnd = qvo.getDate() + " 23:59:59";
		Hospital hospital = hospitalService.getHospitalInfo(hospitalId);
		HashMap<String, Object> data = new HashMap<>();
		data.put("startTime", dateStart);
		data.put("endTime", dateEnd);
		data.put("department", qvo.getDepartment());
		data.put("hospitalId", hospitalId);
		data.put("serviceType", qvo.getServiceType());
		// 1、根据时间获取当日的所有服务信息
		List<OrderNurseDailyReport> serviceInfos = dao.findByDateAndDepartment(data);
		List<OrderNurseDailyReport> temps=new ArrayList<>();
		// 2、对服务信息进行过滤
		for (OrderNurseDailyReport item : serviceInfos) {
			if(matcher.checkMatch(item.getStartTime(), item.getEndTime(), 
					item.getDay(), dateStart, dateEnd, hospital.getCountMethod())){
				temps.add(item);
			}
		}
		serviceInfos=temps;
		int num=0;
		for (OrderNurseDailyReport item : serviceInfos) {
			item.setId(++num);
		}
		// 4、补充服务明细的护工信息,并填充
		//nurseFill(serviceInfos);
		return serviceInfos;
	}
	
	/**
	 * 护工日报
	 */
	@Override
	public SysResult getNurseDailyReport(OrderNurseDailyVo qvo, String hospitalId) {
		List<OrderNurseDailyReport> serviceInfos = findNurseDailyListData(qvo,hospitalId);
		// 3、分页处理
		int total = serviceInfos.size();
		int start = (qvo.getPage() - 1) * qvo.getPageSize();
		int end = qvo.getPage() * qvo.getPageSize() > total ? total : qvo.getPage() * qvo.getPageSize();
		start = end < start ? (end-qvo.getPageSize()) < 0 ? 0 :(end-qvo.getPageSize()) : start;
	//	serviceInfos = serviceInfos.subList(start, end);
		List<OrderNurseDailyReport> subList = serviceInfos.subList(start, end);
		//nurseFill(serviceInfos);
		Set<String> setDepartment = new  HashSet<String>(); 
		Set<String> setWork = new  HashSet<String>(); 
		Float totalPrice=0.0f;
		for (OrderNurseDailyReport orderNurseDailyReport : serviceInfos) {
			setDepartment.add(orderNurseDailyReport.getDepartmentName());
			setWork.add(orderNurseDailyReport.getWorkerName());
			totalPrice+=orderNurseDailyReport.getDayPay();
			if(orderNurseDailyReport.getServiceType().equals(ServiceTypeEnum._2.getKey())){
				orderNurseDailyReport.setDayPay(orderNurseDailyReport.getDayPay()/2);
			}
}
		JSONObject result=new JSONObject();
		result.put("departments", setDepartment.size());
		result.put("workers", setWork.size());
		DecimalFormat df = new DecimalFormat("#.00");
		result.put("totalPrice", Double.parseDouble(df.format(totalPrice)));
		JSONObject pageInfo=new JSONObject();
		pageInfo.put("total", total);
		result.put("pageInfo", pageInfo);
		result.put("list", subList);
		return SysResult.ok(result);
	}

	/**
	 * 填充护工日报数据
	 * @param serviceInfos
	 * @param start
	 */
	private void nurseFill(List<OrderNurseDailyReport> serviceInfos) {
		//int index = 0;
		for (OrderNurseDailyReport orderServiceInfo : serviceInfos) {
			HashMap<String, Object> data = new HashMap<>();
			data.put("orderId", orderServiceInfo.getOrderId());
			data.put("serviceId", orderServiceInfo.getServiceId());
			data.put("version", orderServiceInfo.getVersion());
			List<OrderNurseFullDto> nurseInfos = dao.findByServiceIdAndVersion(data);
			String serviceTypeName = "";
			String workers = "";
			for (OrderNurseFullDto orderServiceNurseInfo : nurseInfos) {
				serviceTypeName = ServiceTypeEnum.valueOf("_" + orderServiceNurseInfo.getServiceType()).getVal();
				workers = orderServiceNurseInfo.getWorkerName() + "/";
			}
			workers = workers.length() > 0 ? workers.substring(0, workers.length() - 1) : "";
			//index++;
			//orderServiceInfo.setId(start + index);// 编号
			orderServiceInfo.setWorkerName(workers);// 护工名称
			orderServiceInfo.setServiceTypeName(serviceTypeName);// 服务类型
			String st = TimeUtils.getStringByDate(orderServiceInfo.getStartTime(), TimeType.yyyy_MM_dd_HH_mm_ss);
			String et = TimeUtils.getStringByDate(orderServiceInfo.getEndTime(), TimeType.yyyy_MM_dd_HH_mm_ss);
			orderServiceInfo.setSvrDay(st + "--" + et);
		}
	}

	/**
	 * 科室日报
	 */
	@Override
	public SysResult getDepartmentDailyReport(DepartmentReportVo dvo, String hospitalId) {
		NurseWokerStatistics nws=new NurseWokerStatistics();
		List<DepartmentDailyReport> reportVos=findDeptDailyListData(dvo,hospitalId,nws,false);
		List<DepartmentDailyReport> pageData =reportVos;
		JSONObject result=new JSONObject();
		result.put("patients", nws.getPatientCount());
		result.put("totalPrice", nws.getTotalAmount());
		result.put("totalWorkers", nws.getNurseWokerCount());
		JSONObject pageInfo=new JSONObject();
		pageInfo.put("total", nws.getTotal());
		result.put("pageInfo", pageInfo);
		result.put("list", pageData);
		/*DepartmentDailyReport ddr=pageData.get(0);
		System.err.println(ddr.toString());*/
		
		return SysResult.ok(result);
	}
	/**
	 * 设置护工名称
	 *@author lcf
	 *@date 2018年8月8日
	 *@version 1.0
	 */
	private void setWokerName(DepartmentDailyReport item,Map<String, String> workerNameMaps){
		if(item.getWorkerId()==null || item.getWorkerId().isEmpty() || workerNameMaps.size()==0){
			item.setWorkerName("");
			return;
		}
		String names=null;
		String[] workerIds = item.getWorkerId().split(",");
		StringBuffer stringBuffer=new StringBuffer();
		for (String workerId : workerIds) {
			if(workerNameMaps.containsKey(workerId)){
				stringBuffer.append(workerNameMaps.get(workerId));
				stringBuffer.append("/");
			}
		}
		if(stringBuffer.length()>1){
		names = stringBuffer.toString().substring(0,stringBuffer.length()-1);
		}
		item.setWorkerName(names);
	}
	
	/**
	 * 根据计算出来的天数和小时，计算总费用
	 *@author lcf
	 *@date 2018年8月9日
	 *@version 1.0
	 */
	private Double calTotalByDate(Integer day,Integer hour,DepartmentDailyReport item){
		Double hourPrice= item.getOneHourPrice();//每小时的单价
		Double dayPrice= item.getActualDayPrice();//每天单价
		Integer _12hour=12;
		Double totalPrice=0.0d;
		Double hourTotalPrice=0.0d;
		Double dayTotalPrice=0.0d;
		if(item.getOrderTypeFlag()==null) return 0.0d;
		else if(item.getOrderTypeFlag()==SysConstant.OrderTypeFlag._12HOUR){//12小时制
			day = day * 24 / _12hour;// 计算出来的天是24小时制，转换成12小时为一天
			if (hour >= _12hour) {// 如果大于等于12小时，直接加一天
				day += 1;
			}
			dayTotalPrice = dayPrice * (day * 1.0d);
			hour=hour%_12hour;
			hourTotalPrice=hourPrice * (hour * 1.0d);// 小时总价
			totalPrice = dayTotalPrice + hourTotalPrice;// 总的费用
			
		}
		else if(item.getOrderTypeFlag()==SysConstant.OrderTypeFlag._24HOUR){//24小时制
			dayTotalPrice=dayPrice*(day*1.0d);//天总价
			hourTotalPrice=hourPrice*(hour*1.0d);//小时总价
			totalPrice=dayTotalPrice+hourTotalPrice;//总的费用
		}
		item.setDays(day);
		if(hour==null) hour=0;
		item.setHours(hour);
		return totalPrice;
	}

	private Double getRecordTotalPrice(DepartmentDailyReport item,Date begin,Date end){
		String dayHourStr=null;
		Integer day=0;
		Integer hour=0;
		dayHourStr=TimeUtils.dateDiff(begin,end);
		day=Integer.parseInt(dayHourStr.split("/")[0]);
		hour=Integer.parseInt(dayHourStr.split("/")[1]);
		return calTotalByDate(day,hour,item);
	}
	
	/**
	 * 计算总费用
	 *@author lcf
	 *@date 2018年8月9日
	 *@version 1.0
	 */
	private Double calRecordTotalCost(DepartmentDailyReport item,String dateStart,String endTime){
		Double totalPrice=0.0d;
		TimeType format=TimeType.yyyy_MM_dd_HH_mm_ss;
		Date recordBeginDate = TimeUtils.getDateByString(item.getBeginTime(), format);
		Date recordEndDate = TimeUtils.getDateByString(item.getEndTime(), format);
		Date startDate=TimeUtils.getDateByString(dateStart, format);
		Date endDate=TimeUtils.getDateByString(endTime, format);
		String[] split = item.getDay().split("[.]");;
		Integer day= Integer.parseInt(split[0]);
		Integer hour=Integer.parseInt(split[1]);
		//1、如果查询出来的开始时间和结束时间在条件时间范围内，直接取总价
		//记录日期大于等于条件日期  并且  记录结束日期小于等于条件日期
		if(recordBeginDate.getTime()>=startDate.getTime() && recordEndDate.getTime()<endDate.getTime()){
			totalPrice=item.getActualTotalPrice();
			item.setDays(day);
			item.setHours(hour);
		}
		//记录开始日期大于条件日期，记录结束日期大于条件结束日期
		else if(recordBeginDate.getTime()>=startDate.getTime() && recordEndDate.getTime()>=endDate.getTime()){
			totalPrice=getRecordTotalPrice(item,recordBeginDate,endDate);
		}
		//记录的开始日期会小于，条件的开始日期，按条件的开始日期开始计算
		//在算结束日期的时候分两种情况
		//1、记录的结束日期不在条件日期范围内（条件结束日期减去条件开始日期） 2、记录的日期在条件日期的范围内(记录日期减去条件日期)
		else if(recordBeginDate.getTime()<startDate.getTime()){
			//记录的结束日期不在条件日期范围内（条件结束日期减去条件开始日期）
			if(recordEndDate.getTime()>endDate.getTime()){
				totalPrice=getRecordTotalPrice(item,startDate,endDate);
			}
			//记录的日期在条件日期的范围内(记录日期减去条件日期)
			else{
				//若订单的开始时间小于查询条件的开始时间，订单的服务结束时间小于查询条件的结束时间，则收据金额=收据金额-（实际日费用*服务天数+实际小时费用*小时数）
				getRecordTotalPrice(item,startDate,recordEndDate);
				//实际日费用*服务天数+实际小时费用*小时数
				Double serverPrice= item.getActualDayPrice()*day+item.getOneHourPrice()*hour;
				if(item.getActualTotalPrice()!=null)
					totalPrice= item.getActualTotalPrice()-serverPrice;
			}
		}
		////如果order_type字段的值为3，表示退款，此时总价的值为负值
		return getActualTotalPrice(item.getOrderType(),totalPrice);
	}
	/**
	 * 查询8月1号至8月1号，如果有一条记录是8月1号8点的单子，如果是12小时制，记录显示的结束时间是8月1号20点，如果是24小时制，记录显示结束日期为:8月2号8点
	 *@author lcf
	 *@date 2018年8月16日
	 *@version 1.0
	 */
	private void setRecordDate(DepartmentDailyReport item,Date queryBegin,Date queryEnd,Date recordBegin,Date recordEnd){
		/**
		 * 1、记录开始时间小于查询开始时间
		 *   实际开始时间=(查询开始日期-记录开始日期)[只求天数，时分秒不参与计算]+记录开始日期(需要加上时分秒)
		 *    如果实际开始时间>=记录结束时间,则丢弃
		 */
		/**
		 * 2、记录结束时间大于查询结束时间时间
		 *  实际结束时间=(查询结束时间-记录开始时间)[只求天数，时分秒不参与计算]+记录开始时间
		 *   如果实际结束时间>=记录结束时间，则取记录结束时间
		 * 
		 */
	}
	
	
	/**
	 * 若订单的开始时间小于查询条件的开始时间，订单的服务结束时间小于查询条件的结束时间，则收据金额=收据金额-（实际日费用*服务天数+实际小时费用*小时数）
	 *@author lcf
	 *@date 2018年8月13日
	 *@version 1.0
	 */
	private Double calReceiptMoney(DepartmentDailyReport item,Date begin,Date end){
		String dayHourStr=null;
		Integer day=0;
		Integer hour=0;
		dayHourStr=TimeUtils.dateDiff(begin,end);
		day=Integer.parseInt(dayHourStr.split("/")[0]);
		hour=Integer.parseInt(dayHourStr.split("/")[1]);
		
		//实际日费用*服务天数+实际小时费用*小时数
		Double serverPrice= item.getActualDayPrice()*item.getDays()+item.getOneHourPrice()*item.getHours();
		if(item.getActualTotalPrice()!=null)
			return item.getActualTotalPrice()-serverPrice;
		return 0.0d;
	}
	
	
	//获取总费用
	private Double getActualTotalPrice(String orderType,Double actualTotalPrice){
		if(isRefund(orderType)) //如果为退款状态，总金额成负数
			return actualTotalPrice*-1;
		else {
			return actualTotalPrice;
		}
	}
	
	//判断是否为退款
	private boolean isRefund(String orderType){
		if(orderType!=null){
			if(orderType.equals(OrderTypeEnum._3.getKey())){
				return true;
			}
		} 
		return false;
	}
	
	/**
	 * nws用于汇总数据患者人数,护工人数,总金额
	 * isAll：代表是否全部数据都要查找出对应的名称
	 */
	@Override
    public List<DepartmentDailyReport> findDeptDailyListData(DepartmentReportVo dvo, String hospitalId,NurseWokerStatistics nws,Boolean isDisplayName ){
		// 3、分页处理
		int total = 0;
		int start = (dvo.getPage() - 1) * dvo.getPageSize();
		List<DepartmentDailyReport> pageData = new ArrayList<>();
		String dateStart = dvo.getBeginTime() + " 00:00:00";
		// String dateEnd = dvo.getEndTime() + " 23:59:59";
		String dateEnd = dvo.getEndTimeAddOneDay();
		// Hospital hospital = hospitalService.getHospitalInfo(hospitalId);
		HashMap<String, Object> data = new HashMap<>();
		data.put("startTime", dateStart);
		data.put("endTime", dateEnd);
		data.put("department", dvo.getDepartment());
		data.put("hospitalId", hospitalId);
		data.put("serviceType", dvo.getServiceType());
		// 只统计已收款
		// if (hospital.getCountMethod() == 11 || hospital.getCountMethod() ==
		// 21) {
		// data.put("payStatus", 1);
		// }
		Double totalPrice = 0.0;
		Double tempTotalPrice = 0.0;
		// 1、查询所有记录
		List<DepartmentDailyReport> reportVos = dao.findDeptDailyReport(data);
		if (reportVos == null || reportVos.size()==0)
			return null;
		reportVos=filter(reportVos, dateStart, dateEnd,nws);
		total = reportVos.size();
		int end = dvo.getPage() * dvo.getPageSize() > total ? total : dvo.getPage() * dvo.getPageSize();
		start = end < start ? (end - dvo.getPageSize()) < 0 ? 0 : (end - dvo.getPageSize()) : start;
		nws.setTotal(total);
		// 根据医院id获取所有的科室
		List<PullDownDto> deparment = deparmnetDao.getDeptByHospitalId(hospitalId);
		Map<String, String> deptMap = PullDownDto.convertToMap(deparment);
		// 获取服务类型
		Map<String, String> servicetype = SysConstant.ServiceTypeCons.SERVICETYPE;
		// 获取所有护工list（组和具体人）,再转成map,转成map目的是查询效率高
		List<NurseWorker> wokerGroupNames = nurseGroupDao.getWokerGroupNameByhospitalId(null);
		// 护工组
		Map<String, String> wokerGroupMap = new HashMap<>();
		// 非护工组
		Map<String, String> wokerMap = new HashMap<>();
		if (wokerGroupNames != null) {
			wokerGroupMap = NurseWorker.convertToMap(wokerGroupNames);
		}
		// 获取所有 非护工组
		List<NurseWorker> wokerNames = nurseGroupDao.getWokerNameByhospitalId(null);
		if (wokerNames != null) {
			wokerMap = NurseWorker.convertToMap(wokerNames);
		}
		// 判断是否显示所有的记录的名称,如果为fase，只统计当前需要展示的页数
		if (isDisplayName) {
			pageData = reportVos;
		} else {
			pageData = reportVos.subList(start, end);
		}
//		//展示名称
		for (DepartmentDailyReport item : pageData) {
			// 设置科室名称
			if (item.getDepartment() != null) {
				if (deptMap.containsKey(item.getDepartment().toString())) {
					item.setDepartmentName(deptMap.get(item.getDepartment().toString()));
				}
			}
			// 设置服务类型名称
			if (item.getServiceType() != null && !item.getServiceType().isEmpty()) {
				if (servicetype.containsKey(item.getServiceType())) {
					item.setServiceTypeName(servicetype.get(item.getServiceType()));
				}
			}
			// 设置护工名称
			if (item.getServiceType() != null) {
				if (item.getServiceType().equals(ServiceTypeEnum._4.getKey())) {
					setWokerName(item, wokerGroupMap);// 当servuce_id为4的时候，取nurse_group表里的组名称
				} else {
					setWokerName(item, wokerMap);// 取nurse_worker_info表里的护工人员的名称，多个人用"/"分隔
				}
			}
		}
		return pageData;
    }
	
	/**
	 * 科室统计报表
	 */
	@Override
	public SysResult getDepartmentCountReport(DepartmentReportVo dvo, String hospitalId) {
		NurseWokerStatistics nws=new NurseWokerStatistics();
		//List<DepartmentCountReport> countReports=findDeptCountListData(dvo,hospitalId,workerMap,patientsMap);
		List<DepartmentCountReport> countReports=findDeptCountListData(dvo,hospitalId,nws);
		JSONObject result=new JSONObject();
		result.put("totalPrice", nws.getTotalAmount());
		result.put("totalWorkers", nws.getNurseWokerCount());
		result.put("totalPatients", nws.getPatientCount());
		JSONObject pageInfo=new JSONObject();
		pageInfo.put("total", countReports.size());
		result.put("pageInfo", pageInfo);
		int total = countReports.size();
		int start = (dvo.getPage() - 1) * dvo.getPageSize();
		int end = dvo.getPage() * dvo.getPageSize() > total ? total : dvo.getPage() * dvo.getPageSize();
		start = end < start ? (end-dvo.getPageSize()) < 0 ? 0 :(end-dvo.getPageSize()) : start;
		List<DepartmentCountReport> pageData=countReports.subList(start, end);
		result.put("list", pageData);
		return SysResult.ok(result);
	}

	/**
	 * 科室统计报表导出
	 */
	@Override
	public List<DepartmentCountReport> findDeptCountListData(DepartmentReportVo dvo, String hospitalId,NurseWokerStatistics nws) {
		List<DepartmentDailyReport> reportVos=findDeptDailyListData(dvo,hospitalId,nws,true);
		if(reportVos==null || reportVos.size()==0) return new ArrayList<>();
		HashMap<String, DepartmentCountReport> maps=new HashMap<>();
		//map<科室,map<护工,开始日期+结束日期>
		Map<String, HashMap<String,String>> workerCountMaps=new HashMap<>();
		Map<String, HashMap<String,String>> patientsMap=new HashMap<>();
		for (DepartmentDailyReport item : reportVos) {
			HashMap<String, Object> data = new HashMap<>();
			data.put("orderId", item.getOrderId());
			data.put("serviceId", item.getServiceId());
			data.put("version", item.getVersion());
			DepartmentCountReport report=maps.get(item.getDepartmentName());
			if(report==null){
				report=new DepartmentCountReport();
				report.setDepartment(item.getDepartment());
				report.setDepartmentName(item.getDepartmentName());
				report.setBeginTime(dvo.getBeginTime());
				report.setEndTime(dvo.getEndTime());
				maps.put(item.getDepartmentName(),report );
			}
			report.setCost(report.getCost()+item.getTotalPrice());
			String[] splitWorkerId = item.getWorkerId().split(",");
			String ptsKey=item.getPhone()+item.getPatientName();
			String dateWhere=item.getPatientName()+item.getBeginTime()+item.getEndTime();
			//统计患者
			HashMap<String, String> ptsMap=patientsMap.get(item.getDepartmentName());
			if(ptsMap==null){
				ptsMap=new HashMap<>();
				ptsMap.put(ptsKey, dateWhere);
				patientsMap.put(item.getDepartmentName(), ptsMap);
			}else {
				if(!item.getOrderType().equals("3")){
					if(!patientsMap.get(item.getDepartmentName()).containsKey(ptsKey)){
						patientsMap.get(item.getDepartmentName()).put(ptsKey, dateWhere);
					}
				}
				/*if(item.getOrderType().equals("3")){
					if(patientsMap.containsKey(item.getDepartmentName())){
						if(patientsMap.get(item.getDepartmentName()).containsKey(ptsKey)){
							if(patientsMap.get(item.getDepartmentName()).get(ptsKey).equals(dateWhere)){
								patientsMap.get(item.getDepartmentName()).remove(ptsKey);
							}
						}
					} 
				}else  {
					if(!patientsMap.get(item.getDepartmentName()).containsKey(ptsKey)){
						patientsMap.get(item.getDepartmentName()).put(ptsKey, dateWhere);
					}
				}*/
			}
			
			//统计护工数
			HashMap<String, String> workMap=workerCountMaps.get(item.getDepartmentName());
			if(workMap==null){
				workMap=new HashMap<>();
				workerCountMaps.put(item.getDepartmentName(), workMap);
			}
			for (String idStr : splitWorkerId) {
				String workIdKey=idStr;
				if (!item.getOrderType().equals("3")) {
					if (!workerCountMaps.get(item.getDepartmentName()).containsKey(workIdKey)) {
						workerCountMaps.get(item.getDepartmentName()).put(workIdKey, dateWhere);
					}
				}
				/*if (item.getOrderType().equals("3")) {//退款
					if (workerCountMaps.containsKey(item.getDepartmentName())) {
						if (workerCountMaps.get(item.getDepartmentName()).containsKey(workIdKey)) {
							if (workerCountMaps.get(item.getDepartmentName()).get(workIdKey).equals(dateWhere)) {
								workerCountMaps.get(item.getDepartmentName()).remove(workIdKey);
							}
						}
					}
				} else {
					if (!workerCountMaps.get(item.getDepartmentName()).containsKey(workIdKey)) {
						workerCountMaps.get(item.getDepartmentName()).put(workIdKey, dateWhere);
					}
				}*/
			}
		}
		for (Entry<String, DepartmentCountReport> item : maps.entrySet()) {
			if(nws.getNurseWokerCount()==0){//护工总数为
				item.getValue().setWorkers(0);
			}else {
				int num=workerCountMaps.get(item.getKey()).size();
				item.getValue().setWorkers(num);
			}
			if(nws.getPatientCount()==0){
				item.getValue().setPatients(0);
			}else {
				item.getValue().setPatients(patientsMap.get(item.getKey()).size());
			}
			
		}
		List<DepartmentCountReport> countReports=new ArrayList<>();
		countReports.addAll(maps.values());
		int num=0;
		for (DepartmentCountReport item : countReports) {
			item.setId(++num);
		}
		return countReports;
	}

	public List<DepartmentDailyReport> filter(List<DepartmentDailyReport> datas, String startTime, String endTime,NurseWokerStatistics nws) {
        List<DepartmentDailyReport> results = new ArrayList<>();
        Map<String,int[]> patients=new HashMap<>();
        Map<String,int[]> workers=new HashMap<>();
        try {
        	int spday=daysBetween(startTime,endTime);
            for (DepartmentDailyReport item : datas) {
                String[] rr=item.getDay().split("\\.");
                int realDay=Integer.parseInt(rr[0]);
                int realHour=Integer.parseInt(rr[1]);
                String[] worker=item.getWorkerId().split(",");
                String patient=item.getPatientName()+item.getPhone();
                int index=0;
                int num=0;
                Boolean need=true;
                int derict=item.getOrderType().equals("3")?0:1;
                int refundFlag=derict==0?-1:1;//如果为退款，就是-1（负1），与相应的值相乘，得负数，否则就是原值
                Double tempTotalPrice=0d;
                if (item.getBeginTime().compareTo(startTime) >= 0 && item.getEndTime().compareTo(endTime) <= 0) {
                    /**
                     * 记录的时间落在完整的查询时间范围内
                     * -2018-08-01 12:00:00&2018-08-02 12:00:00&
                     */
                	item.setDays(realDay*refundFlag);
                	item.setHours(realHour*refundFlag);
                	item.setTotalPrice(item.getActualTotalPrice()*refundFlag);
                    results.add(item);
                    index=daysBetween(startTime,item.getBeginTime());
                } else if (item.getBeginTime().compareTo(startTime) < 0 && item.getEndTime().compareTo(startTime) > 0 && item.getEndTime().compareTo(endTime) < 0) {
                    /**
                     * 记录的尾部时间落在完整的查询时间范围内
                     * 计算开始时间
                     */
                    int day=daysBetween(item.getBeginTime(),startTime);//相差多少天,startTime为结束时间
                    String countDate=addDays(item.getBeginTime(),day);//查询开始时间加上相差的天数
                    if(item.getEndTime().compareTo(countDate)>0){
                    	
                        item.setBeginTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(countDate));
                        item.setDays((realDay-day)*refundFlag);
                        item.setHours(realHour*refundFlag);
                        double cost=item.getActualDayPrice()*day;
                        double price=item.getActualTotalPrice()-cost;
                        item.setTotalPrice(price*refundFlag);
                        results.add(item);
                        index=0;
                    }else{//记录的结束日期小于等于查询的开始日期，则丢弃
                    	need=false;
                    }
                } else if (item.getBeginTime().compareTo(startTime) >= 0 && item.getBeginTime().compareTo(endTime) < 0 && item.getEndTime().compareTo(endTime) > 0) {
                    /**
                     * 记录的头部时间落在完整的查询时间范围内
                     */
                    int day=daysBetween(item.getBeginTime(),endTime);
                    String countDate=addDays(item.getBeginTime(),day);
                    index=daysBetween(startTime,item.getBeginTime());
                    if(item.getEndTime().compareTo(countDate)>0){
                    	Date realEndTime=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(countDate);
                    	if(item.getOrderTypeFlag()==SysConstant.OrderTypeFlag._12HOUR){
                    		realEndTime=TimeUtils.subtractHour(TimeUtils.str2Date(countDate),12);
                    	}
                        item.setEndTime(realEndTime);
                        item.setDays(day*refundFlag);
                        item.setHours(0);
                        double price=item.getActualDayPrice()*day;
                        item.setTotalPrice(price*refundFlag);
                    }else{
                    	item.setDays(realDay*refundFlag);
                    	item.setHours(realHour*refundFlag);
                    	item.setTotalPrice(item.getActualTotalPrice()*refundFlag);
                    }
                    results.add(item);
                   
                    

                } else if (item.getBeginTime().compareTo(startTime) <= 0 && item.getEndTime().compareTo(endTime) >= 0) {
                    /**
                     * 记录的中间段时间落在完整的查询时间范围内
                     */
                    
                    int sday=daysBetween(item.getBeginTime(),startTime);
                    int eday=daysBetween(item.getBeginTime(),endTime);
                    String scDate=addDays(item.getBeginTime(),sday);
                    String ecDate=addDays(item.getBeginTime(),eday);
                    item.setBeginTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(scDate));
                    index=0;
                    if(ecDate.compareTo(item.getEndTime())<0){
                    	Date realEndTime=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ecDate);
                    	if(item.getOrderTypeFlag()==SysConstant.OrderTypeFlag._12HOUR){
                    		realEndTime=TimeUtils.subtractHour(TimeUtils.str2Date(ecDate),12);//减去12小时
                    	}
                        item.setEndTime(realEndTime);
                        item.setDays(spday*refundFlag);
                        item.setHours(0);
                        item.setTotalPrice(spday*item.getActualDayPrice()*refundFlag);
                    }else{
                    	int days=realDay-sday;
                    	if(realHour>0 && days==0){
                    		 item.setDays(0);
                             item.setHours(realHour*refundFlag);
                             item.setTotalPrice((item.getActualTotalPrice()-realDay*item.getActualDayPrice())*refundFlag);
                    	}else{
                    		item.setDays(days*refundFlag);
                            item.setHours(realHour*refundFlag);
                            item.setTotalPrice((item.getActualTotalPrice()-sday*item.getActualDayPrice())*refundFlag);
                    	}
                    }
                    results.add(item);
                }
                if(item.getTotalPrice()!=null){
                nws.setTotalAmount(nws.getTotalAmount()+item.getTotalPrice());
                }else {
					need=false;
				}
                if(need){
                	nws.setTotalAmount(nws.getTotalAmount()+tempTotalPrice);
                	num=Math.abs(item.getDays())+(Math.abs(item.getHours())>0?1:0);
                	doCount(patients,patient,spday,index,num,derict);
                    for (String wr : worker) {
                    	doCount(workers,wr,spday,index,num,derict);
                    	
    				}
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        for (Entry<String, int[]> item : patients.entrySet()) {
        	int ret=0;
			for (int v : item.getValue()) {
				ret+=v;
			}
			if(ret>0){
				nws.setPatientCount(nws.getPatientCount()+1);
			}
		}
        
        for (Entry<String, int[]> item : workers.entrySet()) {
        	int ret=0;
			for (int v : item.getValue()) {
				ret+=v;
			}
			if(ret>0){
				nws.setNurseWokerCount(nws.getNurseWokerCount()+1);
			}
		}

        return results;
    }


    public  int daysBetween(Date smdate,Date bdate) throws ParseException
    {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        smdate=sdf.parse(sdf.format(smdate));
        bdate=sdf.parse(sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days=(time2-time1)/(1000*3600*24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    public int daysBetween(String sdate,String edate)throws ParseException{
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        Date smdate=sdf.parse(sdate);
        Date bdate=sdf.parse(edate);
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days=(time2-time1)/(1000*3600*24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    public String addDays(String stime,int days){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date date = sdf.parse(stime);
            Calendar cl = Calendar.getInstance();
            cl.setTime(date);
            // cl.set(Calendar.DATE, day);
            cl.add(Calendar.DATE, days);
            String result = "";
            result = sdf.format(cl.getTime());
            return result;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return "";
    }
    
    
    public void doCount(Map<String, int[]> datas,String key,int total,int index,int num,int direct) {
		int[] data=datas.get(key);
		if(data==null){
			data=new int[total];
			datas.put(key, data);
		}
		for(int i=0;i<num;i++){
			if(direct>0){
				data[index+i]+=1;
			}else{
				//data[index+i]-=1;
				data[index+i]+=0;
			}
		}
			
	}

}
